/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package net.huangp.dao;

import au.com.bytecode.opencsv.CSVReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import net.huangp.domain.ErrorLog;
import net.huangp.domain.SMS;
import net.huangp.exception.SMSCSVParsingException;
import net.huangp.framework.ThreadContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import static net.huangp.domain.SMSColumn.*;

/**
 *
 * @author Patrick Huang
 */
@Component
public class CSVDAOImpl implements CSVDAO{
    //--------------------------------------------------------------------------
    // Static Properties
    //--------------------------------------------------------------------------
    private static final Logger logger = LoggerFactory.getLogger(CSVDAOImpl.class);
    
    //--------------------------------------------------------------------------
    // Properties
    //--------------------------------------------------------------------------
    private String encoding = "UTF-8";
    // -------------------------------------------------------------------------
    // Implementation Methods
    // -------------------------------------------------------------------------
    public List<SMS> parseCSV(File file) {
        final List<SMS> result = new ArrayList<SMS>();
        if(!file.exists() || !file.canRead()){
            logger.error("csv file[{}] not exist or can not be read",file);
            return result;
        }
        //read file
        //count how many rows in the file
        int count = 0;
        try{
            //we want to make sure we are reading using correct encoding
            InputStreamReader isreader = null;
            if(encoding != null){
                isreader = new InputStreamReader(new FileInputStream(file), encoding);
            }
            else{
                //use system default encoding
                isreader = new FileReader(file);
            }
            CSVReader reader = new CSVReader(isreader);

            SMS sms = null;
            
            
            String[] nextLine = null;
            while ((nextLine = reader.readNext()) != null) {
                count++;
                // nextLine[] is an array of values from the line
                //sms,deliver,"+8613790691229","","","2010.03.29 12:34","","ԀͦȂmessage"
                logger.debug("CSVReader is about to parse:{}",reader.getCurrentLine());
                sms = extractFields(count,nextLine,reader.getCurrentLine());

                if(sms != null){
                //TODO the ability to combine separated MESSAGE.
                //may detect corrupted start character and put it in a temp hash table?
                //after finding the matching MESSAGE, concatenate and return
                    result.add(sms);
                }
            }

        }
        catch(Exception e){
            logger.error("exception",e);
            throw new SMSCSVParsingException(e.toString());
        }
        //after done, remove csv file?
        if(result.size() == count){
            logger.info("all rows in the csv file has been converted to sms.Deleting csv file.");
            file.delete();
        }
        return result;
    }

    /**
     * helper method. extract fields from array and returns a sms object
     * @param lineNum line number
     * @param nextLine
     * @param currentLine current parsing line
     * @return SMS 
     */
    protected SMS extractFields(int lineNum,String[] nextLine,String currentLine) {
        final SMS sms = new SMS();
        try{
            sms.setSender(nextLine[SENDER.column()]);
            sms.setSmsDateTime(csvDateFormatter.parse(nextLine[SMS_DATE_TIME.column()]));
            sms.setMessage(nextLine[MESSAGE.column()]);
            return sms;
        }
        catch(Exception e){
            logger.error("exception during sms field extraction",e);

            ErrorLog log = new ErrorLog();
            String errorLine = "line number: " + lineNum;
            log.setError(errorLine);
            log.setErrorDetail(currentLine);
            ThreadContext.putValue(errorLine, log);
            return null;
        }
    }

    // -------------------------------------------------------------------------
    // Mutator Methods
    // -------------------------------------------------------------------------
    public String getEncoding() {
        return encoding;
    }

    public void setEncoding(String encoding) {
        this.encoding = encoding;
    }
}
